# json language lexer+parser to use with packcc parser generator
%prefix "json"

%source{

#include <stdio.h>

static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" };

#define PCC_DEBUG(event, rule, level, pos, buffer, length) \
    fprintf(stdout, "%*s%s %s @%d [%.*s]\n", (int)(level * 2), "", dbg_str[event], rule, (int)pos, (int)length,  buffer); fflush(stdout)

    /* NOTE: To guarantee the output order, stderr, which can lead a race condition with stdout, is not used. */

}

JSON	<- JSONObject !.

JSONObject	<-  _ '{' _ (Pair _ (_ ',' _ Pair)*)* _ '}' _

Pair	<-  String _ ':' _ Value

Array	<-  _ '[' _ (Value (_ ',' _ Value)* )? _ ']' _

Value	<-
	String
	/ Number
	/ JSONObject
	/ Array
	/ True
	/ False
	/ Null

True	<- "true" _

False	<- "false" _

Null	<- "null" _

String	<- '"' Char* '"' _

Char	<-
	'\\' "\""
	/ '\\' '\\'
	/ '\\' '/'
	/ '\\' 'b'
	/ '\\' 'f'
	/ '\\' 'n'
	/ '\\' 'r'
	/ '\\' 't'
	/ '\\' 'u' Hex Hex Hex Hex
	/ (!"\"" .)

Number	<- minus? int frac? exp?

decimal_point	<- '.'

digit1_9	<- [1-9]

e	<- ['e''E']

exp	<- e (minus / plus)? Digit+

frac	<- decimal_point Digit+

int	<- zero / (digit1_9 Digit*)

minus	<- '-'

plus	<- '+'

zero	<- '0'

Digit	<- [0-9]

Hex	<- [0-9A-Fa-f] _

_	<-		(space / comment)*
space	<-	(' ' / '\t' / endofline)
comment	<-	'#' (!endofline .)*
endofline	<-	( '\r\n' / '\n' / '\r' / '\n\r' )		{ }

%%

int main() {
    json_context_t *ctx = json_create(NULL);
    while (json_parse(ctx, NULL)){;}
    json_destroy(ctx);
    return 0;
}

